const db = require('../db');
const fs = require('fs');
const util = require('util');
const unlinkAsync = util.promisify(fs.unlink);
const multer = require('multer');
const path = require('path');
const { getTypeIdByExtension } = require('../utils/fileClassify');

// 设置multer存储配置
const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    // 设置文件上传的目录为项目根目录下的 src/uploads
    const uploadDir = path.join(__dirname, '../uploads');
    // 确保主上传目录存在
    if (!fs.existsSync(uploadDir)) {
      fs.mkdirSync(uploadDir, { recursive: true });
    }

    // 如果有 fileId，创建一个以 fileId 为名的临时文件夹
    const { fileId, totalChunks } = req.body;
    if (fileId && totalChunks > 1) {
      const tempDir = path.join(uploadDir, fileId);
      if (!fs.existsSync(tempDir)) {
        fs.mkdirSync(tempDir, { recursive: true });
      }
      cb(null, tempDir);
    } else {
      cb(null, uploadDir);
    }
  },
  filename: function (req, file, cb) {
    const originalName = req.body.originalName || file.originalname;
    // 检查是否有分片信息
    if (req.body.index !== undefined) {
      // 使用原始文件名和分片索引构建文件名
      const chunkIndex = req.body.index;
      cb(null, `${originalName}-chunk-${chunkIndex}`); // 构建分片文件名
    } else {
      // 没有分片信息，使用原始文件名
      cb(null, originalName); // 使用原始文件名
    }
  }
});
// 创建multer实例并指定存储配置
const upload = multer({ storage }).fields([
  { name: 'file', maxCount: 1 }, // 用于普通上传
  { name: 'chunk', maxCount: 1 } // 用于分片上传
]);

// 保存文件到数据库
const saveFileInfo = async (userId, folderId, originalName, filePath, fileSize, md5) => {
  console.log("🚀 ~ saveFileInfo ~ userId, folderId, originalName, filePath, fileSize, md5:", userId, folderId, originalName, filePath, fileSize, md5)
  // 查询是不是有md5，有就更新isMerged
  const [md5Result] = await db.query('SELECT * FROM files WHERE md5 = ? AND userId=? AND folderId=?', [md5, userId, folderId]);
  if (md5Result.length > 0) {
    // 更新isMerged
    await db.query('UPDATE files SET isMerged = 1 WHERE md5 = ? AND userId=? AND folderId=?', [md5, userId, folderId]);
    console.log("🚀 ~ saveFileInfo ~ md5.id:", md5.id)
    return md5.id
  }
  const file_name = originalName.slice(0, originalName.lastIndexOf('.'));
  const file_type = originalName.slice(originalName.lastIndexOf('.') + 1);
  const [fileType, typeId] = getTypeIdByExtension(file_type);
  const url = `/uploads/${path.basename(filePath)}`;

  const sql = `INSERT INTO files (userId, folderId, name, size, path, type, typeId, fileType, url,isMerged,md5) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?,?,?)`;
  const [result] = await db.query(sql, [userId, folderId, file_name, fileSize, filePath, file_type, typeId, fileType, url, 1, md5]);
  // 更新users表中的totalSize字段
  if (result.insertId) {
    await db.query('UPDATE users SET totalSize = totalSize + ? WHERE id = ?', [fileSize, userId]);
  }
  return result.insertId;
}
// 上传文件
const uploadFile = async (req, res, next) => {
  try {
    const { files } = req
    let file = files['file'] ? files['file'][0] : null; // 普通上传的文件
    let chunk = files['chunk'] ? files['chunk'][0] : null; // 分片上传的文件

    // 确定是普通文件还是分片
    const fileToProcess = chunk || file;
    // 假设使用了multer中间件处理文件上传，并且文件信息在req.file中
    if (!fileToProcess) {
      return next();
    }
    const { index, totalChunks, fileId, originalName, userId, folderId } = req.body;
    console.log("🚀 ~ uploadFile ~ index, totalChunks, fileId, originalName, userId, folderId:", index, totalChunks, fileId, originalName, userId, folderId)
    const chunkFile = fileToProcess.path;

    // 如果只有一个分片或没有分片信息，则直接保存文件信息
    if (!totalChunks || totalChunks === "1") {
      const file = await saveFileInfo(userId, folderId, originalName, chunkFile, fileToProcess.size, fileId);
      console.log("🚀 ~ uploadFile ~ file:", '走这里')
      res.success({ data: '文件上传成功', file });
    } else {
      // 处理分片上传
      // 检查数据库中是否存在相同的分片记录
      const checkQuery = 'SELECT * FROM file_chunks WHERE fileId = ? AND chunkIndex = ?';
      const [existingChunk] = await db.query(checkQuery, [fileId, index]);
      console.log("🚀 ~ uploadFile ~ existingChunk:", fileId, index)

      if (existingChunk.length > 0) {
        // 如果存在，更新该记录
        await markChunkAsUploaded(fileId, index);
        res.success({ data: '分片更新成功' });
      } else {
        // 如果不存在，插入新的分片记录
        const insertQuery = 'INSERT INTO file_chunks (fileId, chunkIndex, totalChunks, filePath, originalFilename) VALUES (?, ?, ?, ?, ?)';
        await db.query(insertQuery, [fileId, index, totalChunks, chunkFile, originalName]);
        res.success({ data: '分片上传成功' });
      }
    }
  } catch (error) {
    next(error);
  }
};
// 检查分片
const checkChunks = async (req, res, next) => {
  const { fileId, userId, folderId } = req.query;
  const query = 'SELECT * FROM file_chunks WHERE fileId = ? AND userId = ? AND folderId = ?';
  const [rows] = await db.query(query, [fileId, userId, folderId]);
  // 如果不存在分片记录，返回空数组
  if (rows.length === 0) return res.success({ data: rows });
  // 创建一个totalChunks长度的数组
  const uploadedChunks = new Array(rows[0].totalChunks).fill(0);
  // 遍历rows，将已上传的分片索引对应的uploaded字段设置为1
  rows.forEach((row, index) => {
    if (row.uploaded) {
      uploadedChunks[row.chunkIndex] = 1;
    }
  })
  res.success({ data: uploadedChunks });
}
// 添加一个函数来标记分片为已上传
const markChunkAsUploaded = async (fileId, chunkIndex) => {
  // 更新数据库中的分片上传状态
  await db.query('UPDATE file_chunks SET uploaded = 1 WHERE fileId = ? AND chunkIndex = ?', [fileId, chunkIndex]);
};
// 合并分片
const mergeFile = async (req, res, next) => {
  const { fileId, totalChunks, originalName, userId, folderId } = req.body;
  // 检查数据库中是否已存在合并后的文件
  const [existingFile] = await db.query('SELECT * FROM files WHERE userId = ? AND folderId = ? AND md5 = ? AND isMerged = 1', [userId, folderId, fileId]);
  if (existingFile.length > 0) {
    // 文件已存在且已合并
    res.success({ message: '文件已存在且已合并', md5: fileId });
    return;
  }

  const targetDir = path.join(__dirname, '../uploads', fileId);
  const filePath = path.join(__dirname, '../uploads', originalName);
  // 检查是否所有分片都已上传
  const [rows] = await db.query('SELECT COUNT(*) AS count FROM file_chunks WHERE fileId = ?', [fileId]);
  if (rows[0].count == totalChunks) {
    // 合并文件
    fs.writeFileSync(filePath, '');
    for (let i = 0; i < totalChunks; i++) {
      const currentChunkPath = path.join(targetDir, `${originalName}-chunk-${i}`);
      fs.appendFileSync(filePath, fs.readFileSync(currentChunkPath));
      fs.unlinkSync(currentChunkPath); // 删除分片
    }
    fs.rmdirSync(targetDir); // 删除目录

    const fileSize = fs.statSync(filePath).size; // 获取合并后文件的大小
    const md5 = await saveFileInfo(userId, folderId, originalName, filePath, fileSize, fileId);
    res.success({ data: '文件合并成功', md5 });
  } else {
    res.status(400).json({ message: '所有的分片未全部上传.' });
  }
};
// 删除文件
const deleteFile = async (req, res, next) => {
  try {
    const { id } = req.params; // 文件ID
    // 首先获取文件的路径和大小
    const getFileSql = `SELECT path, size, userId FROM files WHERE id = ?`;
    const [files] = await db.query(getFileSql, [id]);

    if (files.length === 0) {
      return res.status(404).json({ message: '文件不存在' });
    }

    const file = files[0];
    const { userId, size } = file;
    // 删除数据库中的文件记录
    const deleteSql = `DELETE FROM files WHERE id = ?`;
    await db.query(deleteSql, [id]);

    // 更新users表中的totalSize字段
    const updateTotalSizeSql = `UPDATE users SET totalSize = totalSize - ? WHERE id = ?`;
    await db.query(updateTotalSizeSql, [size, userId]);

    res.success({ data: '文件删除成功' });
  } catch (error) {
    next(error);
  }

};
// 重命名文件
const renameFile = async (req, res, next) => {
  try {
    const { id, newFileName } = req.body; // 文件ID和新文件名
    const sql = `UPDATE files SET name = ? WHERE id = ?`;
    const [result] = await db.query(sql, [newFileName, id]);

    if (result.affectedRows === 0) {
      return res.status(404).json({ data: '文件未找到或无权修改' });
    }
    res.success({ data: '文件重命名成功' });
  } catch (error) {
    next({ data: '文件重命名失败', error });
  }
};
// 获取文件列表
const getFileList = async (req, res, next) => {
  try {
    const { folderId, userId, typeId } = req.query; // 文件夹ID和用户ID
    // 基础查询
    let sql = `SELECT * FROM files WHERE folderId = ? AND userId = ?`;
    let sqlList = [folderId, userId];

    // 如果 typeId 不为 0，添加额外的条件
    if (typeId != 0) {
      sql = `SELECT * FROM files WHERE typeId = ? AND userId = ?`;
      sqlList = [typeId, userId];
    }

    // 执行文件查询
    const [files] = await db.query(sql, sqlList);
    // 如果 typeId 为 0，还需要查询文件夹
    let data = files;
    console.log("🚀 ~ getFileList ~ data:", sql, sqlList)
    if (typeId == 0) {
      const sqlFolders = `SELECT * FROM folders WHERE folderId = ? AND userId = ?`;
      const [folders] = await db.query(sqlFolders, [folderId, userId]);
      data = [...folders, ...files];
    }
    // 获取用户的 totalSize
    const totalSizeSql = `SELECT totalSize FROM users WHERE id = ?`;
    const [userTotalSize] = await db.query(totalSizeSql, [userId]);
    // 返回成功响应
    res.success({ data: { list: data, totalSize: userTotalSize.length > 0 ? userTotalSize[0].totalSize : 0 } });
  } catch (error) {
    next(error);
  }
};
// 移动文件操作
const updateFile = async (req, res, next) => {
  const { fileList, folderList, folderId } = req.body;
  let connection;
  try {
    // 从连接池中获取一个连接
    connection = await db.getConnection();

    // 开始事务
    await connection.beginTransaction();


    // 如果 fileList 不为空，则更新文件的 folderId
    if (fileList.length > 0) {
      const filePlaceholders = fileList.map(() => '?').join(',');
      const fileSql = `UPDATE files SET folderId = ? WHERE id IN (${filePlaceholders})`;
      await db.query(fileSql, [folderId, ...fileList]);
    }

    // 如果 folderList 不为空，则更新文件夹的 folderId
    if (folderList.length > 0) {
      const folderPlaceholders = folderList.map(() => '?').join(',');
      const folderSql = `UPDATE folders SET folderId = ? WHERE id IN (${folderPlaceholders})`;
      await db.query(folderSql, [folderId, ...folderList]);
    }

    // 提交事务
    await connection.commit();

    // 返回成功响应
    res.success({ data: '文件移动成功' });
  } catch (error) {
    // 如果出现错误，则回滚事务
    if (connection) {
      await connection.rollback();
    }
    // 错误处理
    next(error);
  } finally {
    // 释放连接回连接池
    if (connection) {
      await connection.release();
    }
  }
};
module.exports = {
  upload,
  uploadFile,
  mergeFile,
  deleteFile,
  renameFile,
  getFileList,
  checkChunks,
  updateFile
};